package com.lear.njava.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.lear.njava.pojo.Admin;
import com.lear.njava.pojo.LoginForm;
import com.lear.njava.pojo.Student;
import com.lear.njava.pojo.Teacher;
import com.lear.njava.service.AdminService;
import com.lear.njava.service.StudentService;
import com.lear.njava.service.TeacherService;
import com.lear.njava.util.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.UUID;

// SystemController，针对非表格操作的一些控制层代码，例如登录，获取验证码校验验证码等操作
@Api(tags = "系统控制器")
@RestController
@RequestMapping("/sms/system")
public class SystemController {

    @Autowired // 注入AdminService
    private AdminService adminService;
    @Autowired
    private StudentService studentService;
    @Autowired
    private TeacherService teacherService;

    // POST /sms/system/updatePwd/oldpwd/newpwd
    // 请求参数 oldPwd newPwd token头
    // 响应 Result data = null OK
    @PostMapping("/updatePwd/{oldPwd}/{newPwd}")
    public Result updatePwd(
            @PathVariable("oldPwd") String pldPwd,
            @PathVariable("newPwd") String newPwd,
            @RequestHeader("token") String token // 获取token头
    ){
        // 校验token是否过期
        boolean expiration = JwtHelper.isExpiration(token);
        if (expiration) {
            // token过期
            return Result.fail().message("token过期，请重新登录后修改密码");
        }
        // 获取用户id和用户类型
        Long userId = JwtHelper.getUserId(token);
        Integer userType = JwtHelper.getUserType(token);
        // 密码传过来为明文，需要转换
        pldPwd = MD5.encrypt(pldPwd);
        newPwd = MD5.encrypt(newPwd);
        switch (userType){
            case 1:
                QueryWrapper<Admin> queryWrapper = new QueryWrapper<Admin>();
                queryWrapper.eq("id", userId.intValue());
                queryWrapper.eq("password", pldPwd);
                Admin admin = adminService.getOne(queryWrapper);
                // admin不为null,密码对上了,则进行修改
                if (admin != null) {
                    // 进行修改
                    admin.setPassword(newPwd);
                    adminService.saveOrUpdate(admin);
                }else{
                    return Result.fail().message("原密码有误！");
                }
                break;
            case 2:
                QueryWrapper<Student> queryWrapper2 = new QueryWrapper<Student>();
                queryWrapper2.eq("id", userId.intValue());
                queryWrapper2.eq("password", pldPwd);
                Student student = studentService.getOne(queryWrapper2);
                // admin不为null,密码对上了,则进行修改
                if (student != null) {
                    // 进行修改
                    student.setPassword(newPwd);
                    studentService.saveOrUpdate(student);
                }else{
                    return Result.fail().message("原密码有误！");
                }
                break;
            case 3:
                QueryWrapper<Teacher> queryWrapper3 = new QueryWrapper<Teacher>();
                queryWrapper3.eq("id", userId.intValue());
                queryWrapper3.eq("password", pldPwd);
                Teacher teacher = teacherService.getOne(queryWrapper3);
                // admin不为null,密码对上了,则进行修改
                if (teacher != null) {
                    // 进行修改
                    teacher.setPassword(newPwd);
                    teacherService.saveOrUpdate(teacher);
                }else{
                    return Result.fail().message("原密码有误！");
                }
                break;

        }
        return Result.ok();
    }

    // POST /sms/system/headerImgUpload
    @ApiOperation("文件上传统一入口")
    @PostMapping("/headerImgUpload")
    public Result headerImgUpload(
            @ApiParam("头像文件") @RequestPart("multipartFile") MultipartFile multipartFile // 将图片赋给MultipartFile对象
    ){
        // 1.保存文件 2.响应文件路径
        // 通过UUID避免图片名称冲突
        String uuid = UUID.randomUUID().toString().replace("-", "").toLowerCase();
        String originalFilename = multipartFile.getOriginalFilename();
        // 寻找originalFilename中最后一个点出现的位置
        int i = originalFilename.lastIndexOf(".");
        // 从点开始往后截取，获取文件后缀
        String substring = originalFilename.substring(i);
        // 拼接新文件名
        String newFileName = uuid + substring;
        // 保存文件，实际情况下通常将文件发送到第三方/独立的图片服务器上，然后将服务器上存储图片的URL拿到，然后响应过来
        // 这里将路径写死
        String portraitPath = "E:/实习项目/java/project/learnja/src/main/resources/static/upload/".concat(newFileName);
        try {
            multipartFile.transferTo(new File(portraitPath));
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 响应文件路径
        String path = "upload/".concat(newFileName);
        return Result.ok(path);
    }

    @GetMapping("/getInfo")
    public Result getInfoByToken(@RequestHeader("token") String token){ //从请求头获得信息往参数上放
        // 校验token是否过期
        boolean expiration = JwtHelper.isExpiration(token);
        if (expiration) {
            return Result.build(null, ResultCodeEnum.TOKEN_ERROR); //过期
        }
        // 从token中解析出用户id和类型
        Long userId = JwtHelper.getUserId(token);
        Integer userType = JwtHelper.getUserType(token);
        // 判断用户类型
        Map<String, Object> map = new LinkedHashMap<>();

        switch (userType){
            case 1:
                Admin admin = adminService.getAdminById(userId);
                map.put("userType", 1);
                map.put("user", admin);
                break;
            case 2:
                Student student = studentService.getStudentById(userId);
                map.put("userType", 2);
                map.put("user", student);
                break;
            case 3:
                Teacher teacher = teacherService.getTeacherById(userId);
                map.put("userType", 3);
                map.put("user", teacher);
                break;
        }
        return Result.ok(map); // 将map加入result对象
    }

    @PostMapping("/login")
    public Result login(@RequestBody LoginForm loginForm, HttpServletRequest request){
        // 1.验证码校验
        // 2.从session中移除现有验证码，验证码用过了就失效了
        // 3.分用户类型进行校验
//        1.
        HttpSession session = request.getSession(); //用request对象获取session
        String sessionVerifiCode = (String)session.getAttribute("verifiCode"); //从session中拿出verifiCode,是一个字符串
        String loginVerifiCode = loginForm.getVerifiCode(); //另一个verifiCode在loginform里面
        if("".equals(sessionVerifiCode) || null == sessionVerifiCode){ //输入空验证码或者验证码失效
            return Result.fail().message("验证码失效，请刷新后重试");
        }
        if (!sessionVerifiCode.equalsIgnoreCase(loginVerifiCode)){ //判断前后端验证码是否相同
            return Result.fail().message("验证码有误，请小心输入后重试");
        }
//        2.
        session.removeAttribute("verifiCode");
//        3.
        // 准备一个map用于存放用户响应的数据
        Map<String, Object> map = new LinkedHashMap<>();
        switch (loginForm.getUserType()){
            case 1:
                try {
                    Admin admin = adminService.login(loginForm); //使用service层根据用户名和密码查询数据库有没有admin
//                如果admin不为null
                    if (null != admin) {
                        // 将用户的类型和用户的id转换成密文，以token的形式向用户端反馈
                        String token = JwtHelper.createToken(admin.getId().longValue(), 1);
                        map.put("token", token);
                    }else {
                        throw new RuntimeException("用户名或密码错误");
                    }
                    return Result.ok(map);
                } catch (RuntimeException e) {
                    e.printStackTrace();
                    return Result.fail().message(e.getMessage());
                }
            case 2:
                try {
                    Student student = studentService.login(loginForm); //使用service层根据用户名和密码查询数据库有没有student
//                如果admin不为null
                    if (null != student) {
                        // 将用户的类型和用户的id转换成密文，以token的形式向用户端反馈
                        String token = JwtHelper.createToken(student.getId().longValue(), 2);
                        map.put("token", token);
                    }else {
                        throw new RuntimeException("用户名或密码错误");
                    }
                    return Result.ok(map);
                } catch (RuntimeException e) {
                    e.printStackTrace();
                    return Result.fail().message(e.getMessage());
                }
            case 3:
                try {
                    Teacher teacher = teacherService.login(loginForm); //使用service层根据用户名和密码查询数据库有没有admin
//                如果admin不为null
                    if (null != teacher) {
                        // 将用户的类型和用户的id转换成密文，以token的形式向用户端反馈
                        String token = JwtHelper.createToken(teacher.getId().longValue(), 3);
                        map.put("token", token);
                    }else {
                        throw new RuntimeException("用户名或密码错误");
                    }
                    return Result.ok(map);
                } catch (RuntimeException e) {
                    e.printStackTrace();
                    return Result.fail().message(e.getMessage());
                }
        }
        return Result.fail().message("查无此用户");
    }

    @GetMapping("/getVerifiCodeImage")
    public void getVerifiCodeImage(HttpServletRequest request, HttpServletResponse response){
        // 1.获取图片
        // 2.获取图片上的验证码
        // 3.将验证码图片放入session域，为下一次验证做准备
        // 4.将验证码图片响应给浏览器
//        1.
        BufferedImage verifiCodeImage = CreateVerifiCodeImage.getVerifiCodeImage();
//        2.
//        char[] verifiCode = CreateVerifiCodeImage.getVerifiCode();
//        以char数组形式返回，通过string的构造方法将char转换成字符串
        String verifiCode = new String(CreateVerifiCodeImage.getVerifiCode());
//        3.
//        通过request对象获取session
//        往session里面设置一个verifiCode
        HttpSession session = request.getSession();
        session.setAttribute("verifiCode", verifiCode);
//        4.
//        通过response对象将图片响应给浏览器
//        将图片通过输出流发送过去
        try {
            ServletOutputStream outputStream = response.getOutputStream();
//        ImageIO工具类可以直接将图片通过输出流写出去
            ImageIO.write(verifiCodeImage, "JPEG", outputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
